import java.io.*;
import java.net.*;

public class ReliableUDPClient {
    private static final int PACKET_SIZE = 1024;
    private static final int WINDOW_SIZE = 3;

    public static void main(String[] args) {
        DatagramSocket clientSocket = null;
        try {
            clientSocket = new DatagramSocket();
            InetAddress serverAddress = InetAddress.getByName("localhost");
            int serverPort = 9876;

            int sequenceNumber = 0;
            int windowBase = 0;

            byte[] fileData = readFileData("D:/123.txt");

            while (windowBase < fileData.length) {
                int windowEnd = Math.min(windowBase + WINDOW_SIZE, fileData.length);
                for (int i = windowBase; i < windowEnd; i++) {
                    int currentSequenceNumber = sequenceNumber % 256;
                    byte[] sendData = new byte[PACKET_SIZE];
                    sendData[0] = (byte) currentSequenceNumber;
                    System.arraycopy(fileData, i, sendData, 1, Math.min(PACKET_SIZE - 1, fileData.length - i));

                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverAddress, serverPort);
                    clientSocket.send(sendPacket);

                    // 等待确认
                    byte[] receiveData = new byte[PACKET_SIZE];
                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    clientSocket.receive(receivePacket);

                    String ackMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
                    System.out.println("收到确认: " + ackMessage);
                }

                // 移动窗口
                windowBase += WINDOW_SIZE;
                sequenceNumber += WINDOW_SIZE;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (clientSocket != null && !clientSocket.isClosed()) {
                clientSocket.close();
            }
        }
    }

    private static byte[] readFileData(String filePath) throws IOException {
        // Implement the logic to read data from the file
        try (FileInputStream fis = new FileInputStream(filePath)) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[PACKET_SIZE - 1];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            return bos.toByteArray();
        }
    }
}

